{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import scipy.stats\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "import math\n",
    "import pandas as pd"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1. Найдите минимально необходимый объем выборки для построения интервальной оценки среднего с точностью ∆ = 3, дисперсией σ^2 = 225 и уровнем доверия β = 0.95."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Необходимое минимальное число человек для опроса: 68\n"
     ]
    }
   ],
   "source": [
    "delta = 3\n",
    "std = 225**0.5\n",
    "beta = 0.95\n",
    "\n",
    "# Оругляем полученное значение в большую сторону\n",
    "N = math.ceil((std * scipy.stats.norm.ppf(beta) / delta)**2)\n",
    "\n",
    "print('Необходимое минимальное число человек для опроса:', N)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2. Вам даны две выборки роста мужчин и женщин. Докажите, используя t-Тест Стьдента, что различия между выборками незначительно, если уровень значимости равен 0.001"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "population_men   = scipy.stats.norm.rvs(loc=19,scale=171,size=11000000)  # Выборка мужчин со средним ростом 171\n",
    "population_women = scipy.stats.norm.rvs(loc=16,scale=165,size=12000)     # Выборка женщин со средним ростом 165"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "H0 - Выборки мужчин и женщин не отличаются  \n",
    "H1 - Различия в выборках мужчин и женщин статистически значимы\n",
    "\n",
    "Используем t-критерий для несвязанных выборок. Так как дисперсии отличаются, указываем параметр equal_var = False"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Гипотеза H0 верна, различия в выборках мужчин и женщин статистически не значимы на уровне 0.1%\n"
     ]
    }
   ],
   "source": [
    "alpha = 0.001\n",
    "t, p = scipy.stats.ttest_ind(population_men, population_women, equal_var=False)\n",
    "\n",
    "if p < alpha:\n",
    "    print(f'Отклоняем гипотезу H0, различия в выборках мужчин и женщин статистически значимы на уровне {alpha :.1%}')\n",
    "else:\n",
    "    print(f'Гипотеза H0 верна, различия в выборках мужчин и женщин статистически не значимы на уровне {alpha :.1%}')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3. Определите объем необходимой выборки для исследования среднего чека за кофе в случайном городе, если известно, что в этом городе стандартное отклонение = 150, уровень доверия = 95%. Погрешность 50 рублей. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Необходимое минимальное число человек для опроса: 25\n"
     ]
    }
   ],
   "source": [
    "delta = 50\n",
    "std = 150\n",
    "beta = 0.95\n",
    "\n",
    "# Оругляем полученное значение в большую сторону\n",
    "N = math.ceil((std * scipy.stats.norm.ppf(beta) / delta)**2)\n",
    "\n",
    "print('Необходимое минимальное число человек для опроса:', N)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4.  Представьте, что вы хотите разоблачить \"волшебника\", который считает, что умеет предсказывать погоду на завтра. Отвечая просто: дождь или солнце. Вы пронаблюдали за ответами \"волшебника\" в течении какого периода времени и получили такие результаты (см.ниже). Можно ли сказать, что маг действительно умеет предсказывать погоду, если уровнь значимости принять за 0.05 ?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Ответ волшебника</th>\n",
       "      <th>Реальность</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>Дождь</th>\n",
       "      <td>14</td>\n",
       "      <td>36</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Солнце</th>\n",
       "      <td>15</td>\n",
       "      <td>45</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "        Ответ волшебника  Реальность\n",
       "Дождь                 14          36\n",
       "Солнце                15          45"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "alpha = 0.05\n",
    "\n",
    "observations = pd.DataFrame([[14,36],[15,45]],\n",
    "                            index=['Дождь','Солнце'],\n",
    "                            columns=['Ответ волшебника','Реальность'])\n",
    "observations"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Ответы волшебника и данные реальности можно считать независимыми выборками. Так как мы имеем 4-х польную таблицу с категориальными признаками и ни одно значение в ней не меньше 10, то для оценки статистической значимости можно выбрать критерий хи-квадрата Пирсона.\n",
    "\n",
    "H0 - Волшебник умеет предсказывать погоду, данные волшебника и реальности не отличаются  \n",
    "H1 - Волшебник не умеет предсказывать погоду, различия между ответами волшебника и реальности статистически значимы"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Гипотеза H0 верна, волшебник умеет предсказывать погоду, различия данных волшебника и реальности статистически не значимы на уровне 5.0%\n"
     ]
    }
   ],
   "source": [
    "chi2, p, ddof, expected = scipy.stats.chi2_contingency(observations)\n",
    "\n",
    "if p < alpha:\n",
    "    print(f'Отклоняем гипотезу H0, Волшебник не умеет предсказывать погоду, различия между ответами волшебника и реальности \\\n",
    "    статистически значимы на уровне {alpha :.1%}')\n",
    "else:\n",
    "    print(f'Гипотеза H0 верна, волшебник умеет предсказывать погоду, различия данных волшебника и реальности \\\n",
    "статистически не значимы на уровне {alpha :.1%}')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Так как у нас категориальных признаков не больше 2, то данные позволяют нам провести проверку с помощью точного критерия Фишера."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Гипотеза H0 верна, волшебник умеет предсказывать погоду, различия данных волшебника и реальности статистически не значимы на уровне 5.0%\n"
     ]
    }
   ],
   "source": [
    "oddsratio, p = scipy.stats.fisher_exact(observations)\n",
    "\n",
    "if p < alpha:\n",
    "    print(f'Отклоняем гипотезу H0, Волшебник не умеет предсказывать погоду, различия между ответами волшебника и реальности \\\n",
    "    статистически значимы на уровне {alpha :.1%}')\n",
    "else:\n",
    "    print(f'Гипотеза H0 верна, волшебник умеет предсказывать погоду, различия данных волшебника и реальности \\\n",
    "статистически не значимы на уровне {alpha :.1%}')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 5. Используя функцию mean_confidence_interval(data, confidence), постройте доверительный интервал с уровнем доверия 90% для выборки: \n",
    "\n",
    "data = [1,5,8,9,6,7,5,6,7,8,5,6,7,0,9,8,4,6,7,9,8,6,5,7,8,9,6,7,5,8,6,7,9,5]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "def mean_confidence_interval(data:list, confidence:float, ttype:str='normal', two_tailed:bool=True):\n",
    "    \"\"\"\n",
    "    Функция для расчета доверительного интервала для массива данных с заданным уровнем доверия.\n",
    "    \n",
    "    Входные параметры:\n",
    "        data -- массив значений\n",
    "        confidence -- уровень доверия (вероятность)\n",
    "        ttype -- тип распределения, принимает значения 'student' или 'normal'. По умолчанию 'normal'.\n",
    "        two_tailed -- признак двустороннего теста, если True - выполняем двусторонний тест, иначе односторонний.\n",
    "                      По умолчанию True.\n",
    "        \n",
    "    Возвращаемые значения: (нижняя граница интервала, среднее, верхняя граница интервала)\n",
    "    \"\"\"\n",
    "    \n",
    "    ttype = ttype.lower().strip()\n",
    "    ttype_correct_values = ('student', 'normal')\n",
    "    \n",
    "    if confidence < 0 or confidence > 1:\n",
    "        raise ValueError('Параметр confidence должен принимать значения в диапазоне от 0 до 1')\n",
    "        \n",
    "    if ttype not in ttype_correct_values:\n",
    "        raise ValueError(f'Параметр ttype может принимать только следующие значения: {\",\".join(ttype_correct_values)}')\n",
    "        \n",
    "    if not isinstance(two_tailed, bool):\n",
    "        raise TypeError(f'Значение параметра two_tailed должно иметь тип bool')\n",
    "       \n",
    "    n = len(data)\n",
    "    sem = scipy.stats.sem(data)\n",
    "    mean = np.mean(data)\n",
    "    \n",
    "    # Для двустороннего теста требуется поделить уровень значимости на 2 части\n",
    "    if two_tailed:\n",
    "        confidence = (1+confidence)/2\n",
    "    \n",
    "    if ttype == 'normal':\n",
    "        ppf = scipy.stats.norm.ppf(confidence)\n",
    "    else:\n",
    "        ppf = scipy.stats.t.ppf(confidence, n-1)\n",
    "        \n",
    "    h = sem * ppf\n",
    "    \n",
    "    return mean-h, mean, mean+h"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(5.961614036054297, 6.628571428571429, 7.295528821088561)"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data = [4,5,8,9,6,7,5,6,7,8,5,6,7,0,9,8,4,6,7,9,8,6,5,7,8,9,6,7,5,8,6,7,9,5,10]\n",
    "\n",
    "# Так как у нас выборка мала, то выбираем распределение Стьюдента, выбираем двусторонний тест\n",
    "mean_confidence_interval(data, confidence=0.95, ttype='student', two_tailed=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 6. Принадлежит ли выборка data_1 и data_2 одному множеству? Оцените это с помощью известных вам тестов проверки гипотез."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "data_1 = [4,5,8,9,6,7,5,6,7,8,5,6,7,0,9,8,4,6,7,9,8,6,5,7,8,9,6,7,5,8,6,7,9,5,10]\n",
    "data_2 = [8,5,6,7,0,1,8,4,6,7,0,2,6,5,7,5,3,5,3,5,3,5,5,8,7,6,4,5,3,5,4,6,4,5,3,2,6,4,2,6,1,0,4,3,5,4,3,4,\n",
    "          5,4,3,4,5,4,3,4,5,3,4,4,1,2,4,3,1,2,4,3,2,1,5,3,4,6,4,5,3,2,4,5,6,4,3,1,3,5,3,4,4,4,2,5,3]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "H0 - отличий между data_1 и data_2 нет  \n",
    "H1 - выборки data_1 и data_2 отличаются\n",
    "\n",
    "Так как нам даны 2 выборки без разделения по категориальным признакам, то нам подойдут критерии для сравнения среднего значения или сравнения дисперсий.\n",
    "\n",
    "Если предполагать, что выбрки независимые, то можно провести тесты по следующим критериям:\n",
    "- Критерий Стьюдента для независимых выборок\n",
    "- Критерий Манна-Уитни\n",
    "\n",
    "Если предполагать, что выборки зависимы, то можно вопользоваться следующими критериями:\n",
    "- Критерий Стьюдента для зависимых выборок\n",
    "- Критерий Уилкоксона\n",
    "\n",
    "Но так как наши данные имеют различный размер, то такие тесты сделать не получится.\n",
    "\n",
    "Также тесты могут быть односторонними или левосторонними."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Верна гипотеза H1: выборки data_1 и data_2 отличаются на уровне значимости 5.0%\n"
     ]
    }
   ],
   "source": [
    "# Критерий Стьюдента для независимых выборок\n",
    "stat, p = scipy.stats.ttest_ind(data_1, data_2)\n",
    "alpha = 0.05\n",
    "\n",
    "#Для двустороннего теста\n",
    "if p < alpha:\n",
    "    print(f'Верна гипотеза H1: выборки data_1 и data_2 отличаются на уровне значимости {alpha :.1%}')\n",
    "else:\n",
    "    print(f'Верна гипотеза H0: выборки data_1 и data_2 не отличаются на уровне значимости {alpha :.1%}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Верна гипотеза H1: выборки data_1 и data_2 отличаются на уровне значимости 5.0%\n"
     ]
    }
   ],
   "source": [
    "#Для одностороннего теста\n",
    "if p/2 < alpha:\n",
    "    print(f'Верна гипотеза H1: выборки data_1 и data_2 отличаются на уровне значимости {alpha :.1%}')\n",
    "else:\n",
    "    print(f'Верна гипотеза H0: выборки data_1 и data_2 не отличаются на уровне значимости {alpha :.1%}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Верна гипотеза H1: выборки data_1 и data_2 отличаются на уровне значимости 5.0%\n"
     ]
    }
   ],
   "source": [
    "# Критерий Манна-Уитни\n",
    "stat, p = scipy.stats.mannwhitneyu(data_1, data_2)\n",
    "alpha = 0.05\n",
    "\n",
    "#Для двустороннего теста\n",
    "if p < alpha:\n",
    "    print(f'Верна гипотеза H1: выборки data_1 и data_2 отличаются на уровне значимости {alpha :.1%}')\n",
    "else:\n",
    "    print(f'Верна гипотеза H0: выборки data_1 и data_2 не отличаются на уровне значимости {alpha :.1%}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Верна гипотеза H1: выборки data_1 и data_2 отличаются на уровне значимости 5.0%\n"
     ]
    }
   ],
   "source": [
    "#Для одностороннего теста\n",
    "if p/2 < alpha:\n",
    "    print(f'Верна гипотеза H1: выборки data_1 и data_2 отличаются на уровне значимости {alpha :.1%}')\n",
    "else:\n",
    "    print(f'Верна гипотеза H0: выборки data_1 и data_2 не отличаются на уровне значимости {alpha :.1%}')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 7. На примере датасета про жилье в New York City, мы сталкивались с примером, когда переменная имеет не совсем нормальное распределение. \n",
    "\n",
    "### Предположим, Вы сформировали две гипотезы: Нулевая гипотеза - распределение нормальное,  Альтернативная гипотеза - распределение не нормальное.\n",
    "\n",
    "\n",
    "### Допустим, вы применили какой-то тест (сейчас неважно какой), который показал уровень значимости (p-value) = 0.03. Каковы будут ваши выводы? Будем считать что у нас нормальное распределение или все-таки нет? Вопрос без подвоха)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Если мы примем уровень значимости 0.05, то при p-value = 0.03 можно сказать, что наше распределение не является нормальным на уровне значимости 5%. При этом нельзя точно сказать, что наше распределение является нормальным или не нормальным. Мы предполагаем, что наше распределение не нормальное, но есть вероятность в 5%, что мы допустили ошибку и отклонили верную гипотезу H0 о нормальности нашего распределения. \n",
    "\n",
    "Если принять уровень значимости 0.01 (ужесточение требований), то в данном случае мы можем сказать, что наша гипотеза H0 верна на уровне значимости 1%."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 8. Первая выборка — это пациенты, которых лечили препаратом А.  Вторая выборка — пациенты, которых лечили препаратом Б. Значения в выборках — это некоторая характеристика эффективности лечения (уровень метаболита в крови, температура через три дня после начала лечения, срок выздоровления, число койко-дней, и т.д.) \n",
    "\n",
    "#### а) Требуется выяснить, имеется ли значимое различие эффективности препаратов А и Б, или различия являются чисто случайными и объясняются «естественной» дисперсией выбранной характеристики?  (уровень значимости принять за 5% или 0.05)\n",
    "\n",
    "#### b) При каком минимальном P-values различия были бы уже значимы? "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Предполагается независимость выборок. Если представить, что наши значения - количество койко-дней, то нас будет интересовать только правая сторона плотности распределения значений, когда этих койко-дней очень много, а если их мало, то это значит, что человек быстро выздоровел. Поэтому будем выполнять односторонний тест с помощью критерия Стьюдента для независимых выборок."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Эффективность препаратов отличается на уровне значимости 5.0%\n"
     ]
    }
   ],
   "source": [
    "np.random.seed(11)\n",
    "A = scipy.stats.norm.rvs(scale=50,loc=10,size=300)\n",
    "B = scipy.stats.norm.rvs(scale=10,loc=-1.25,size=300)\n",
    "alpha = 0.05\n",
    "\n",
    "stat, p = scipy.stats.ttest_ind(A, B, equal_var=False)\n",
    "if p < alpha:\n",
    "    print(f'Эффективность препаратов отличается на уровне значимости {alpha :.1%}')\n",
    "else:\n",
    "    print(f'Эффективность препаратов одинакова на уровне значимости {alpha :.1%}')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Разиличя будут значимы, если p-value будет меньше принятого нами уровня значимости. А уровень значимости мы можем как повышать, так и понимажть в зависимости от нашей задачи. В одних задачах уровень надо наоборот ужесточать, как в случае исследования воздействия препаратов, а в других случаях можно увеличивать. Это должно быть обоснованно. Для уровня значимости 0.05 p-value должен быть меньше этого значения чтобы различия были значимыми для этого уровня."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
